package com.baizhi.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import java.util.Set;

@Component
@Aspect
public class RedisAspect {

    @Autowired
    private RedisTemplate redisTemplate;

    //清除缓存
    //如果执行了增删改  成功后执行清除
    //后置 业务方法执行完毕
    @After("execution(* com.baizhi.service.*Impl.*(..)) && !execution(* com.baizhi.service.*Impl.*(..))")
    public void deleteCache(JoinPoint joinPoint){
        String className = joinPoint.getTarget().getClass().getName();
        //比如现在执行用户的增删改 会执行UserServiceImpl
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.delete(className);
        /*Set keys = redisTemplate.keys("*");
        for (Object key : keys) {
            if(((String)key).startsWith(className)){
                redisTemplate.delete(key);
            }
        }*/

    }


    //添加缓存
    @Around("execution(* com.baizhi.service.*Impl.query*(..))")
    public Object addCache(ProceedingJoinPoint proceedingJoinPoint){
        /*System.out.println("进入环绕通知");
        System.out.println("进入环绕前置");*/
        //redis(key value)形式存储数据
        //key:包名+类名+方法名+实参
        //value:缓存数据

        //获取类名
        StringBuilder sb = new StringBuilder();
        String className = proceedingJoinPoint.getTarget().getClass().getName();
        System.out.println("类名"+className);
//        sb.append(className);
        //获取方法名
        String methodName = proceedingJoinPoint.getSignature().getName();
        System.out.println(methodName);
        sb.append(methodName);
        //获取参数
        Object[] args = proceedingJoinPoint.getArgs();
        for (Object arg : args) {
            System.out.println("实参"+arg);
            sb.append(arg);
        }
        //使用redisTemplate之前取消键的序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //redis中的key
        String key = sb.toString();
//        Boolean flag = redisTemplate.hasKey(key);
        //操作redis值是字符串类型的操作对象
        HashOperations hashOperations = redisTemplate.opsForHash();
        Boolean flag = hashOperations.hasKey(className, key);
        if(flag){
            //redis有数据(缓存)   如果有直接从缓存中获取
            return  hashOperations.get(className,key);   //返回到controller
        }else{
            //没有缓存  如果没有就放行请求 到达service(调用dao)走数据库
            try {
                Object proceed = proceedingJoinPoint.proceed();//放行就回到达业务层(会调用dao走数据库能够查出数据)，返回给controller
                hashOperations.put(className,key,proceed);
                return proceed;
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
        //判断redis中是否有缓存数据
        //如果有 直接从缓存中获取
        //如果没有就放行 请求到达servic shujukue(调用dao)u

        return null;
    }
}
